# coding=utf-8

import uuid

from django.db import transaction
from django.core.exceptions import ObjectDoesNotExist
from django.core import serializers
from django.forms.models import model_to_dict

from forms import *
from common import config


class TaskServices(object):
    def __init__(self):
        self.task = None

    @staticmethod
    def create_task(uid, task_base, task_ext, sub_task, task_files):
        if uid is None or len(task_base) == 0 or len(task_ext) == 0:
            raise Exception('参数错误')

        # todo 需要重构，可以将is_valid()方法放在save()方法中调用，使得代码尽量简介
        try:
            with transaction.atomic():
                task_ext_form = TaskExtForm(task_ext, task_files)
                if task_ext_form.is_valid():
                    task_ext_entity = task_ext_form.save()

                    task_base = dict(task_base.items() + {'task_ext': task_ext_entity.pk}.items())
                    task_base['task_num'] = uuid.uuid1()
                    task_base_form = TaskBaseForm(task_base, task_files)
                    if task_base_form.is_valid():
                        task_base_entity = task_base_form.save()
                        print task_base_entity.pk

                        for item in sub_task:
                            item_task = dict(task_base.items() + {'task': task_base_entity.pk}.items())
                            item_task['describe'] = item.get('describe')
                            item_task['task_value'] = item.get('task_value')
                            item_task['task_num'] = uuid.uuid1()
                            sub_task_form = TaskBaseForm(item_task, task_files)
                            if sub_task_form.is_valid():
                                sub_task_form.save()
                            else:
                                raise BaseException(sub_task_form.errors)

                        # task_sensor = dict(task_sensor.items() + {'task': task_base_entity.pk}.items())
                        # task_sensor_form = TaskSensorForm(task_sensor)
                        # if task_sensor_form.is_valid():
                        #     task_sensor_form.save()
                        # else:
                        #     raise BaseException(task_sensor_form.errors)
                    else:
                        raise BaseException(task_base_form.errors)
                else:
                    raise BaseException(task_ext_form.errors)

                return {'status': True, 'msg': task_base_entity.pk}
        except BaseException as e:
            return {'status': False, 'msg': e.message}

    @staticmethod
    def get_task_list(last_id, order_type, type_task, data_type, industry):
        """
        获取任务列表
        task ext: type_task industry
        task base: data_type
        """
        task_list = []
        if type_task is 0 and industry is 0:
            task_ext_lists = TaskExt.find_tasks().values()
        elif type_task is 0 and industry is not 0:
            task_ext_lists = TaskExt.find_tasks(industry=industry).values()
        elif type_task is not 0 and industry is 0:
            task_ext_lists = TaskExt.find_tasks(type_task=type_task).values()
        else:
            task_ext_lists = TaskExt.find_tasks(type_task=type_task, industry=industry).values()

        for task_ext in task_ext_lists:
            if data_type is not 0:
                task_base = TaskBase.find_tasks(data_type=data_type, task_ext=task_ext.get('id')).values()
            else:
                task_base = TaskBase.find_tasks(task_ext=task_ext.get('id')).values()
            if len(task_base) == 0:
                continue
            del task_ext['id']
            task_base = [dict(x.items() + task_ext.items()) for x in task_base]
            task_list = task_list + task_base

        task_list = {
            0: task_list,
            1: task_list.sort(key=lambda task: task.get('task_value'), reverse=True),
            2: task_list,
            3: task_list.sort(key=lambda task: task.get('last_update'), reverse=True)
        }[order_type]

        return task_list[last_id:last_id+20]

    @classmethod
    def get_data_list(cls, last_id, data_type):
        data_list = []
        tasks_data = UserDataTask.objects.filter(station=data_type)
        for data in tasks_data:
            task_base = model_to_dict(data.task_base)
            data = model_to_dict(data)
            data['data_file'] = data['data_file'].name
            del task_base['demo'], task_base['icon_task'], task_base['template']
            data_list.append(dict(task_base.items() + data.items()))
        return data_list[last_id:last_id+20]

    @classmethod
    def get_check_list(cls, last_id):
        task_list = []
        task_bases = TaskBase.objects.filter(station=1)
        for task in task_bases:
            task_ext = model_to_dict(task.task_ext)
            task_base = model_to_dict(task)
            del task_ext['id'], task_base['demo'], task_base['icon_task'], task_base['template']
            task_list.append(dict(task_base.items() + task_ext.items()))
        print task_list
        return task_list[last_id:last_id+20]

    @staticmethod
    def get_task(task_base_id):
        if 0 >= task_base_id:
            return None

        try:
            task_base = TaskBase.objects.get(pk=task_base_id)
            task_base = dict(model_to_dict(task_base).items() + {
                'create_time': task_base.create_time.strftime("%Y-%m-%d %H:%I:%S"),
                'update_time': task_base.update_time.strftime("%Y-%m-%d %H:%I:%S"),
                'over_time': task_base.over_time.strftime("%Y-%m-%d %H:%I:%S"),
                'last_time': task_base.last_time.strftime('%Y-%m-%d %H:%I:%S'),
                'start_time': task_base.start_time.strftime('%Y-%m-%d %H:%I:%S'),
            }.items())
            print task_base

            task_ext = model_to_dict(TaskExt.objects.get(pk=task_base.get('task_ext')))
            task_base['icon_task'] = task_base.get('icon_task').name
            task_base['demo'] = task_base.get('demo').name
            task_base['template'] = task_base.get('template').name
            task_base['username'] = User.objects.get(pk=task_base['user']).nickname
            del task_ext['id']
        except ObjectDoesNotExist:
            return None
        return dict(task_ext.items() + task_base.items())

    @classmethod
    def user_join_task(cls, user_id, task_base_id, post_price=None):
        if cls.check_can_join(user_id, task_base_id) is False:
            return {
                'status': False,
                'msg': '已经报名该任务',
            }

        try:
            task_base = TaskBase.objects.get(pk=task_base_id)
            if task_base is None:
                raise ObjectDoesNotExist('object not found')
            join_form = UserJoinForm({
                'user': user_id,
                'task_base': task_base_id,
                'post_price': 0 if post_price is None else post_price,
                'station': 0
            })
            if join_form.is_valid():
                join_form.save()
                return {'status': True, 'msg': ''}
            else:
                return {'status': False, 'msg': join_form.errors}
        except ObjectDoesNotExist as e:
            return {'status': False, 'msg': e.message}

    @classmethod
    def check_can_join(cls, user_id, task_base_id):
        user_join = UserJoinTask.objects.filter(user_id=user_id, task_base_id=task_base_id)
        print user_join
        if len(user_join) is 0:
            return True
        return False

    @staticmethod
    def upload_task_data(user_id, task_base_id, data_brief, data_file):
        try:
            task_base = TaskBase.objects.get(pk=task_base_id)
            upload_form = UserDataForm(
                data={
                    'user': user_id,
                    'task_base': task_base.pk,
                    'data_brief': data_brief
                },
                files=data_file
            )
            if upload_form.is_valid():
                upload_form.save()
                return {'status': True, 'msg': ''}
            else:
                return {'status': False, 'msg': upload_form.errors}
        except ObjectDoesNotExist as e:
            return {'status': False, 'msg': e.message}

    @classmethod
    def into_task_upload(cls, user_id, task_id):
        try:
            task_base = cls.get_task(task_id)
            user_join = UserJoinTask.objects.get(task_base_id=task_id, user_id=user_id)
            user_join = dict(model_to_dict(user_join).items() + {
                'join_time': user_join.join_time.strftime('%Y-%m-%d %H:%I:%S'),
                'end_time': user_join.end_time.strftime('%Y-%m-%d %H:%I:%S'),
            }.items())
            return {
                'task': task_base,
                'user_join': user_join,
            }
        except ObjectDoesNotExist as e:
            pass

    @classmethod
    def update_task_data(cls, user_id, data_id, task_base_id, data_text, data_brief, data_file):
        try:
            user_data = UserDataTask.objects.get(pk=data_id)
            task_base = TaskBase.objects.get(pk=task_base_id)
            if user_data.station == config.config.get('task_edit'):
                station = config.config.get('task_back')
            else:
                station = user_data.station
            upload_from = UserDataForm(
                data={
                    'user': user_id,
                    'task_base': task_base.pk,
                    'data_text': data_text,
                    'data_brief': data_brief,
                    'data_file': data_file,
                    'station': station
                },
                files=data_file,
                instance=user_data
            )
            if upload_from.is_valid():
                upload_from.save()
                return {'status': True, 'msg': ''}
            else:
                return {'status': False, 'msg': upload_from.errors}
        except ObjectDoesNotExist as e:
            return {'status': False, 'msg': e.message}

    @staticmethod
    def user_user_tasks(user_id, last_id, station):
        station = config.config.get(station)
        task_list = UserJoinTask.objects.filter(user_id=user_id, station=station).values()
        for task in task_list:
            task_base = TaskServices.get_task(task.get('task_base_id'))
            task['task'] = task_base
        return task_list[last_id:last_id+20]

    @staticmethod
    def get_publish_task(user_id, last_id):
        task_bases = TaskBase.objects.filter(user=user_id)
        task_list = []
        for task_base in task_bases:
            task = TaskServices.get_task(task_base.pk)
            task_list.append(task)
        return task_list[last_id:last_id+20]

    @staticmethod
    def user_join_info(user_id, task_id):
        try:
            user_task = UserJoinTask.objects.get(user_id=user_id, task_base_id=task_id)
            return user_task
        except ObjectDoesNotExist:
            return None

    @classmethod
    def task_join_user(cls, user_id, task_base_id):
        try:
            task_base = TaskBase.objects.get(pk=task_base_id, user=user_id)
            task_user = UserJoinTask.objects.filter(task_base=task_base.pk)
            user_list = []
            for item in task_user:
                user_list.append({
                    'nickname': item.user.nickname,
                    'user_id': item.user.pk,
                    'join_time': item.join_time.strftime('%Y-%m-%d %H:%I:%S'),
                    'station': item.station,
                })
            return {'status': True, 'msg': user_list}
        except ObjectDoesNotExist as e:
            return {'status': False, 'msg': e.message}

    @classmethod
    def agree_user_join(cls, user_id, task_base_id, joiner_ids):
        try:
            task_base = TaskBase.objects.get(pk=task_base_id, user=user_id)
            if task_base.station >= 5:
                raise BaseException('已经被分配')

            for joiner_id in joiner_ids:
                join_task = UserJoinTask.objects.get(user=joiner_id, task_base=task_base_id)
                if join_task.station is not config.config.get('task_join') \
                        or join_task.station is config.config.get('task_running'):
                    raise ObjectDoesNotExist('已经被分配任务')
                join_form = UserJoinForm({
                    'station': 1,
                    'task_base': task_base.pk,
                }, instance=join_task)
                if join_form.is_valid():
                    join_form.save()
                else:
                    raise BaseException(join_form.errors)
            task_base.station = 5
            task_base.save()
            return {'status': True, 'msg': ''}
        except ObjectDoesNotExist as e:
            return {'status': False, 'msg': e.message}
        except BaseException as e:
            return {'status': False, 'msg': e.message}

    @classmethod
    def find_task_data(cls, user_id, task_base_id):
        try:
            task_base = TaskBase.objects.get(user=user_id, pk=task_base_id)
            task_data = UserDataTask.objects.filter(task_base=task_base.pk,
                                                    station=config.config.get('task_over'))
            data_list = []
            for task in task_data:
                task_item = model_to_dict(task)
                task_item['data_file'] = task.data_file.name
                task_item['update_time'] = task.update_time.strftime('%Y-%m-%d %H:%I:%S')
                data_list.append(task_item)
            return {'status': True, 'msg': data_list}
        except ObjectDoesNotExist as e:
            return {'status': 'error', 'msg': e.message}

    @classmethod
    def create_comment(cls, user_id, to_user, task, rank, comment):
        user_comment_form = UserTaskCommentForm({
            'user': user_id,
            'to_user': to_user,
            'task': task,
            'rank': rank,
            'comment': comment
        })
        if user_comment_form.is_valid():
            user_comment_form.save()
            return {'status': True, 'msg': ''}
        else:
            return {'status': False, 'msg': user_comment_form.errors}

    @classmethod
    def pass_check(cls, task_id):
        try:
            task_base = TaskBase.objects.get(pk=task_id)
            task_base.station = 4
            task_base.save()
            return True
        except ObjectDoesNotExist as e:
            return True

    @classmethod
    def pass_data(cls, data_id):
        try:
            task_data = UserDataTask.objects.get(pk=data_id)
            task_data.station = 6
            task_data.save()
            return True
        except ObjectDoesNotExist as e:
            return True

    @classmethod
    def prevent_check(cls, task_id):
        try:
            task_base = TaskBase.objects.get(pk=task_id)
            task_base.station = 2
            task_base.save()
            return True
        except ObjectDoesNotExist as e:
            return True

    @classmethod
    def prevent_data(cls, data_id):
        try:
            task_data = UserDataTask.objects.get(pk=data_id)
            task_data.station = 4
            task_data.save()
            return True
        except ObjectDoesNotExist as e:
            return True
